package com.demo.bean;

import com.demo.aop.DefaultAopProxyFactory;
import com.demo.aop.advisor.Advisor;

import java.lang.reflect.Method;
import java.util.*;

public class CreateProxyBeanPostProcess implements BeanPostProcessor{
    @Override
    public Object beforeBeanInitMethod(BeanFactory beanFactory, String beanname, Object instance){
        return instance;
    }

    @Override
    public Object afterBeanInitMethod(BeanFactory beanFactory, String beanname, Object instance) throws Exception {
        List<Advisor> matchAdvisor = getMatchAdvisor(beanFactory, instance);
        if(matchAdvisor!=null && !matchAdvisor.isEmpty()){
            return new DefaultAopProxyFactory().createAopProxy(instance, beanname, matchAdvisor, beanFactory).getProxy();
        }
        return instance;
    }

    private List<Advisor> getMatchAdvisor(BeanFactory beanFactory,Object instance){
        List<Advisor> advisors = beanFactory.getAdvisors();
        List<Advisor> matchAdvisors = new ArrayList<>(advisors.size());
        Class<?> instanceClass = instance.getClass();
        Set<Method> methodSet = new HashSet<>();
        methodSet.addAll(Arrays.asList(instanceClass.getMethods()));
        methodSet.addAll(Arrays.asList(instanceClass.getDeclaredMethods()));

        for (Advisor advisor : advisors) {
            if(!advisor.getPointcut().matchClass(instanceClass)){
                continue;
            }
            for (Method method : methodSet) {
                if(advisor.getPointcut().matchMethod(instanceClass,method)){
                    matchAdvisors.add(advisor);
                    break;
                }
            }
        }
        return matchAdvisors;
    }

}
